// 返回值包装器
package object

import (
	"bytes"
	"fmt"
	"hash/fnv"
	"lark/src/ast"
	"strconv"
	"strings"
	"sync"
)

type BuiltinFunction func(args ...Object) Object

type ObjectType string

const (
	NULL_OBJ    = "NULL"
	ERROR_OBJ   = "ERROR"
	BOOLEAN_OBJ = "BOOLEAN"

	IDENTIFIER_OBJ    = "IDENTIFIER"
	INTEGER_OBJ       = "INTEGER"
	FLOAT_OBJ         = "FLOAT"
	STRING_OBJ        = "STRING"
	RETURN_VALUE_OBJ  = "RETURN_VALUE"
	FUNCTION_OBJ      = "FUNCTION"
	IMPORT_OBJ        = "IMPORT"
	MODULE_OBJ        = "MODULE"
	MODULE_ACCESS_OBJ = "MODULE_ACCESS"

	BUILTIN_OBJ       = "BUILTIN"
	ARRAY_OBJ         = "ARRAY"
	HASH_OBJ          = "HASH"
	DATE_OBJ          = "DATE"
	EMPTY_OBJ         = "EMPTY"
	HTTP_RESPONSE_OBJ = "HTTP_RESPONSE"
	OBJECT_TYPE       = "OBJECT_TYPE"
)

type HashKey struct {
	Type  ObjectType
	Value uint64
}

type Hashable interface {
	HashKey() HashKey
}

type Object interface {
	Type() ObjectType
	Inspect() string
	GetProperty(name string) (Object, bool) // 统一属性访问接口
}

// 整数
type Integer struct {
	Value int64
}

func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
func (i *Integer) Inspect() string  { return fmt.Sprintf("%d", i.Value) }
func (i *Integer) HashKey() HashKey {
	return HashKey{Type: i.Type(), Value: uint64(i.Value)}
}
func (i *Integer) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

// 浮点数
type Float struct {
	Value float64
}

func (i *Float) Type() ObjectType { return FLOAT_OBJ }
func (i *Float) Inspect() string  { return fmt.Sprintf("%g", i.Value) }
func (i *Float) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

// 字符串
type String struct {
	Value string
}

func (s *String) Type() ObjectType { return STRING_OBJ }
func (s *String) Inspect() string  { return s.Value }
func (s *String) HashKey() HashKey {
	h := fnv.New64a()
	h.Write([]byte(s.Value))

	return HashKey{Type: s.Type(), Value: h.Sum64()}
}
func (i *String) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

// 标识符
type Identifier struct {
	Value string
}

func (i *Identifier) Type() ObjectType { return IDENTIFIER_OBJ }
func (i *Identifier) Inspect() string  { return i.Value }
func (i *Identifier) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type ReturnValue struct {
	Value Object
}

func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }
func (rv *ReturnValue) Inspect() string  { return rv.Value.Inspect() }
func (i *ReturnValue) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Boolean struct {
	Value bool
}

func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
func (b *Boolean) Inspect() string  { return fmt.Sprintf("%t", b.Value) }
func (b *Boolean) HashKey() HashKey {
	var value uint64

	if b.Value {
		value = 1
	} else {
		value = 0
	}

	return HashKey{Type: b.Type(), Value: value}
}
func (i *Boolean) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Null struct{}

func (n *Null) Type() ObjectType { return NULL_OBJ }
func (n *Null) Inspect() string  { return "null" }
func (i *Null) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Error struct {
	Message string      //描述
	Code    int         //错误代码
	File    string      //文件
	Line    int         //行号
	Stack   []CallFrame // 调用栈信息
}

// 调用栈帧
type CallFrame struct {
	FunctionName string
	Line         int
	Column       int
}

func (e *Error) Type() ObjectType { return ERROR_OBJ }
func (e *Error) Inspect() string {
	msg := "\n行号:%s\n错误:%s\n"
	return fmt.Sprintf(msg, strconv.Itoa(e.Line), e.Message)
}
func (i *Error) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Function struct {
	Name       string
	Parameters []*ast.Identifier
	Body       *ast.BlockStatement
	Env        *Environment
}

func (f *Function) Type() ObjectType { return FUNCTION_OBJ }
func (f *Function) Inspect() string {
	var out bytes.Buffer

	params := []string{}
	for _, p := range f.Parameters {
		params = append(params, p.String())
	}

	out.WriteString("fn")
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") {\n")
	out.WriteString(f.Body.String())
	out.WriteString("\n}")

	return out.String()
}
func (i *Function) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Builtin struct {
	Fn     BuiltinFunction
	Fields map[string]BuiltinFunction // 用于动态添加字段
}

func (b *Builtin) Type() ObjectType { return BUILTIN_OBJ }
func (b *Builtin) Inspect() string  { return "builtin function" }
func (i *Builtin) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Import struct {
	Path string
	As   string // 可选的别名
}

func (i *Import) Type() ObjectType { return IMPORT_OBJ }
func (i *Import) Inspect() string  { return i.Path }
func (i *Import) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Module struct {
	Name      string
	Symbols   *Environment
	IsLibrary bool // 是否为标准库模块
	Exports   map[string]Object
}

func (m *Module) Type() ObjectType { return MODULE_OBJ }
func (m *Module) Inspect() string {
	var out bytes.Buffer
	out.WriteString(fmt.Sprintf("module %s {\n", m.Name))
	/* for name, obj := range m.Symbols.All() {
		out.WriteString(fmt.Sprintf("  %s = %s\n", name, obj.Inspect()))
	} */
	out.WriteString("}")
	return out.String()
}
func (m *Module) GetProperty(name string) (Object, bool) {
	obj, ok := m.Exports[name]
	return obj, ok
}

type ModuleAccess struct {
	mu         sync.RWMutex // 并发安全锁
	ModuleName string
	Name       string
	Symbols    *Environment
	parent     *ModuleAccess // 父模块(用于嵌套模块)
	IsLibrary  bool          // 是否为标准库模块
	Fn         NativeFunction
}

func (ma *ModuleAccess) Type() ObjectType { return MODULE_ACCESS_OBJ }
func (ma *ModuleAccess) Inspect() string {
	var out bytes.Buffer
	out.WriteString(fmt.Sprintf("moduleAccess %s {\n", ma.ModuleName))
	out.WriteString("}")
	return out.String()
}
func (i *ModuleAccess) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

//================= start 自定义函数 =================//

type Array struct {
	Elements []Object
}

func (ao *Array) Type() ObjectType { return ARRAY_OBJ }
func (ao *Array) Inspect() string {
	var out bytes.Buffer

	elements := []string{}
	for _, e := range ao.Elements {
		elements = append(elements, e.Inspect())
	}

	// out.WriteString("[")
	out.WriteString(strings.Join(elements, ","))
	// out.WriteString("]")

	return out.String()
}
func (i *Array) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type HashPair struct {
	Key   Object
	Value Object
}

type Hash struct {
	Pairs map[HashKey]HashPair
}

func (h *Hash) Type() ObjectType { return HASH_OBJ }
func (h *Hash) Inspect() string {
	var out bytes.Buffer

	pairs := []string{}
	for _, pair := range h.Pairs {
		pairs = append(pairs, fmt.Sprintf("\"%s\": \"%s\"", pair.Key.Inspect(), pair.Value.Inspect()))
	}

	out.WriteString("{")
	out.WriteString(strings.Join(pairs, ", "))
	out.WriteString("}")

	return out.String()
}
func (i *Hash) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Date struct {
	Value string
}

func (i *Date) Type() ObjectType { return DATE_OBJ }
func (i *Date) Inspect() string  { return i.Value }
func (i *Date) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

type Empty struct {
	Value bool
}

func (e *Empty) Type() ObjectType { return EMPTY_OBJ }
func (e *Empty) Inspect() string  { return fmt.Sprintf("%t", e.Value) }
func (i *Empty) GetProperty(name string) (Object, bool) {
	// 整数类型通常没有属性，返回nil和false
	return nil, false
}

// ================= end 自定义函数 =================//

// HttpResponse 表示HTTP响应对象
type HttpResponse struct {
	StatusCode int               // HTTP状态码
	Status     string            // 状态文本
	Headers    map[string]string // 响应头
	Body       string            // 响应体(字符串)
	Duration   float64           // 请求耗时(秒)
}

func (r *HttpResponse) Type() ObjectType { return HTTP_RESPONSE_OBJ }
func (r *HttpResponse) Inspect() string {
	return fmt.Sprintf("HttpResponse{StatusCode: %d, Status: %s, Body: %q, Duration: %f}", r.StatusCode, r.Status, r.Body, r.Duration)
}

// GetProperty 获取属性
func (r *HttpResponse) GetProperty(name string) (Object, bool) {
	switch name {
	case "status_code":
		return &Integer{Value: int64(r.StatusCode)}, true
	case "status":
		return &String{Value: r.Status}, true
	case "body":
		return &String{Value: r.Body}, true
		/* case "headers":
		headers := make(map[Object]Object)
		for k, v := range r.Headers {
			headers[&String{Value: k}] = &String{Value: v}
		}
		return &Hash{Pairs: headers}, true */
	}
	return nil, false
}

// Value 脚本语言值接口
type Value interface {
	Type() int
	String() string
}

// NativeFunction 原生函数类型
type NativeFunction func(args ...Object) Object

// StdLib 标准库对象值
type StdLib struct {
	Properties map[string]Value
	Methods    map[string]NativeFunction
}

/*
	type Instance struct {
		Class  *Class
		Fields map[string]Object
	}

func (i *Instance) Type() Type      { return OBJECT }
func (i *Instance) Inspect() string { return fmt.Sprintf("instance:%s", i.Class.Name) }

	func (i *Instance) GetProperty(name string) (Object, bool) {
		val, ok := i.Fields[name]
		if !ok {
			// 检查类方法
			if method, ok := i.Class.Methods[name]; ok {
				return &BoundMethod{
					Receiver: i,
					Method:   method,
				}, true
			}
		}
		return val, ok
	}
*/
type ObjectWithProperties interface {
	Object
	GetProperty(name string) (Object, bool)
	SetProperty(name string, value Object) bool
}

type BaseObject struct {
	Class      string
	Properties map[string]Object
}

func (o *BaseObject) Type() ObjectType { return OBJECT_TYPE }
func (o *BaseObject) Inspect() string {
	return fmt.Sprintf("%s object", o.Class)
}

func (o *BaseObject) GetProperty(name string) (Object, bool) {
	prop, ok := o.Properties[name]
	return prop, ok
}

func (o *BaseObject) SetProperty(name string, value Object) bool {
	o.Properties[name] = value
	return true
}
